/*
 * ===========================================================================
 *
 *       Filename:  qfmode.c
 *    Description:  qf4a512 mode
 *                  1. Set gpio to qf4a512 spi mode: CONFIGURE or RUN.
 *                  2. qf4a512 status
 *
 *        Version:  0.2.1
 *       Modified:  2011.06.12 15:22
 *       Modified:  2011.01.14 21:50
 *       Modified:  2010.12.23 20:41
 *        Created:  12/21/10 20:17:24
 *         Author:  LYF (Liu Yunfeng), liuyf.nju@gmail.com
 *
 * ===========================================================================
 */

#include <stdio.h>
#include <unistd.h>
#include "include/qfmode.h"
#include "include/gpio.h"

#define  uchar  unsigned char
#define  ushort unsigned short
#define  CHANNEL_NUM	3

unsigned short qf_rdonly_reg[]={
	0x000c, 
	0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,	
	0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
	0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
	0x00ea,
	0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5,
	0x00f6,	0x00f7, 0x00f8,	0x00f9, 0x00fa,
	0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
};

int qf_reg_isreadonly(unsigned short addr)
{
	int i;
	int length = sizeof(qf_rdonly_reg)/sizeof(qf_rdonly_reg[0]);

	for( i=0 ; i < length ; i++ )
	{
		if( addr == qf_rdonly_reg[i] )
			return 1;
	}
	return 0;
}

void qf_reset(void)
{
	CLR(P_RST);
	sleep(1);
	SET(P_RST);
}

void qf_port_init(void)
{
	set_output(P_CS);
	set_output(P_RST);
	set_output(P_DI);
	set_output(P_CLK);
	set_input(P_INT);
	set_input(P_DO);
	SET(P_CS);
	SET(P_RST);
	CLR(P_CLK);
}

void qf_configure_read(ushort address, uchar *value)
{
	ushort odata;
	uchar idata = 0 ;
	int n;
	odata = ( (address << 1) | 0x8000 );

	//CLR(P_INT);
	SET(P_CS);
	CLR(P_CLK);
	CLR(P_CS);
	for( n=15 ; n >= 0 ; n-- )
	{
		( (odata >> n) & 0x01 ) ? SET(P_DI) : CLR(P_DI) ;
		SET(P_CLK);
		CLR(P_CLK);
	}
	for( n=7 ; n >= 0 ; n-- )
	{
		SET(P_CLK);
		if( RDP(P_DO) ) { idata |= ( 1 << n ); }
		CLR(P_CLK);
	}
	SET(P_CS);

	*value = idata;
	//printf("Read ok.\n");
}

void qf_configure_write(unsigned short address, unsigned char value)
{
	ushort odata;
	int n;
	unsigned int i;

	odata = ( (address << 1) & 0x7fff );

	//CLR(P_INT);
	SET(P_CS);
	CLR(P_CLK);
	CLR(P_CS);
	for( n=15 ; n >= 0 ; n-- )
	{
		( (odata >> n) & 0x01 ) ? SET(P_DI) : CLR(P_DI) ;
		SET(P_CLK);
		CLR(P_CLK);
	}
	for( n=7 ; n >= 0 ; n-- )
	{
		( (value >> n) & 0x01 ) ? SET(P_DI) : CLR(P_DI) ;
		SET(P_CLK);
		CLR(P_CLK);
	}
	SET(P_CS);
	//printf("Write ok.\n");
}

void qf_run_mode(unsigned char ctrl_addr, unsigned char ctrl_data, 
		unsigned char *data_flag, unsigned short *data)
{
	/***
	 * Run when P_INT shows signal.
	 ***/
	int n, cid;

	/* waiting P_INT to 1 */
	while( RDP(P_INT) == 0 ) {;};
	CLR(P_CS);
	/* waiting P_INT to 0 */
	while( RDP(P_INT) == 1 ) {;};

	for( cid = 0 ; cid< CHANNEL_NUM ; cid++ )
	{
		uchar flag = 0;
		ushort value = 0;
		
		for( n=7 ; n>=0 ; n-- )
		{
			( (ctrl_addr >> n) & 0x01 ) ? SET(P_DI) : CLR(P_DI) ;
			SET(P_CLK);
			if( RDP(P_DO) ) { flag |= ( 1 << n ); }
			CLR(P_CLK);
		}
		for( n=7 ; n>=0 ; n-- )
		{
			( (ctrl_data >> n) & 0x01 ) ? SET(P_DI) : CLR(P_DI) ;
			SET(P_CLK);
			if( RDP(P_DO) ) { value |= ( 1 << n ); }
			CLR(P_CLK);
		}
		value = ( value << 8 );
		for( n=7 ; n>=0 ; n-- )
		{
			SET(P_CLK);
			if( RDP(P_DO) ) { value |= ( 1 << n ); }
			CLR(P_CLK);
		}
	
		*(uchar *) (data_flag + cid) = flag;
		*(ushort *)(data      + cid) = value;
	}
	SET(P_CS);
}





